//
// Created by DELL on 2024/2/29.
//
#include <iostream>
#include <queue>
#include <functional>
#include <thread>
#include <mutex>
#include <atomic>

class BlockQueue
{
public:
    using Msg = std::function<void()>;

    void enqueue(const Msg& msg)
    {
        std::lock_guard guard(mutex);
        queue.push(msg);
        condition.notify_one();
    }

    Msg dequeue()
    {
        std::unique_lock lock(mutex);
        condition.wait(lock, [this](){ return !queue.empty(); });

        auto msg = std::move(queue.front());
        queue.pop();
        return msg;
    }

    void notify()
    {
        condition.notify_one();
    }

private:
    std::queue<Msg> queue;
    std::mutex mutex;
    std::condition_variable condition;
};



int main()
{
    BlockQueue queue;

    queue.enqueue([](){
        std::cout << "Msg1" << std::endl;
    });
    queue.enqueue([](){
        std::cout << "Msg2" << std::endl;
    });

    queue.enqueue([](){
        std::cout << "Msg3" << std::endl;
    });

    queue.enqueue([](){
        std::cout << "Msg4" << std::endl;
    });


    std::atomic_bool exitThread{false};
    std::thread thread1([&queue, &exitThread](){
        while (!exitThread)
        {
            auto msg = queue.dequeue();
            msg();
            std::this_thread::sleep_for(std::chrono::milliseconds(2000));
        }
    });

    std::thread thread2([&queue, &exitThread](){
        while (!exitThread)
        {
            auto msg = queue.dequeue();
            msg();
            std::this_thread::sleep_for(std::chrono::milliseconds(2000));
        }
    });

    queue.enqueue([](){
        std::cout << "Msg5" << std::endl;
    });
    queue.enqueue([](){
        std::cout << "Msg6" << std::endl;
    });

    std::this_thread::sleep_for(std::chrono::milliseconds(18000));
    exitThread = true;

    queue.enqueue([](){
        std::cout << "Exit1" << std::endl;
    });
    queue.enqueue([](){
        std::cout << "Exit2" << std::endl;
    });

    thread1.join();
    thread2.join();

    return 0;
}